/* Turska UI library
 * Copyright 2003-2008 Jetro Lauha
 * All rights reserved.
 * Web: http://iki.fi/jetro/ or http://jet.ro
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of EITHER:
 *   (1) The GNU Lesser General Public License as published by the Free
 *       Software Foundation; either version 2.1 of the License, or (at
 *       your option) any later version. The text of the GNU Lesser
 *       General Public License is included with this library in the
 *       file LICENSE-LGPL.txt.
 *   (2) The BSD-style license that is included with this library in
 *       the file LICENSE-BSD.txt.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
 * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
 *
 * $Id: UIFontOpenGLSDL.cpp,v 1.6 2008/03/27 11:44:26 tonic Exp $
 * $Revision: 1.6 $
 */

#include "SDL.h"
#include "UI.h"


UIFontOpenGLSDL::UIFontOpenGLSDL(UIGraphicsOpenGLSDL *graphics, const char *fileName, const char *fontString,
                                 UINT8 alphaTraceMinAlpha) :
    UIFont(fileName, fontString),
    mGraphics(graphics),
    mAlphaTraceMinAlpha(alphaTraceMinAlpha)
{
}


UIFontOpenGLSDL::~UIFontOpenGLSDL()
{
}


BOOL UIFontOpenGLSDL::init()
{
    return reload();
}


BOOL UIFontOpenGLSDL::reload()
{
    SDL_Surface *image;
    UINT32 g, x, y, x1, x2;

    if (mLoaded && mGlyphs != NULL)
    {
        UINT32 a;
        for (a = 0; a < mGlyphCount; ++a)
            delete mGlyphs[a];
        delete[] mGlyphs;
        mGlyphs = NULL;
        mGlyphCount = 0;
    }
    mLoaded = FALSE;

    image = mGraphics->loadSurface(mFileName);
    if (image == NULL)
        return FALSE;

    mGlyphCount = image->h / image->w;
    if (mGlyphCount < 1)
    {
        SDL_FreeSurface(image);
        return FALSE;
    }
    mGlyphs = new UIImage *[mGlyphCount];

    mFontHeight = image->w;

    for (g = 0; g < mGlyphCount; ++g)
    {
        INT32 w, h;
        SDL_LockSurface(image);
        x1 = image->w;
        x2 = 0;
        for (x = 0; (int)x < image->w; ++x)
        {
            for (y = g * image->w; y < (g + 1) * image->w; ++y)
            {
                const Uint32 pixel = *(UINT32 *)((UINT8 *)image->pixels +
                    y * image->pitch + x * image->format->BytesPerPixel);
                Uint8 red, green, blue, alpha = 0;
                SDL_GetRGBA(pixel, image->format, &red, &green, &blue, &alpha);
                UINT8 traceMinAlpha = mAlphaTraceMinAlpha;
                if ((image->flags & SDL_SRCALPHA) == 0)
                {
                    alpha = red | green | blue; // TODO: Better handling of alpha when image doesn't have it.
                    traceMinAlpha = 0;
                }
                // trace right edge
                if (alpha > traceMinAlpha && x > x2)
                    x2 = x;
                // trace left edge
                if (alpha > traceMinAlpha && x < x1)
                    x1 = x;
            }
        }
        SDL_UnlockSurface(image);
        if (x1 > x2)
        {
            w = image->w / 3;
            h = image->w;
            x1 = 0;
            x2 = w;
        }
        else
        {
            w = x2 - x1 + 1;
            //w += 2;
            //if (w > image->w)
            //    w = image->w;
            h = image->w;
        }

        UIRectangle area;
        area.x = x1;
        area.y = g * image->w;
        area.w = w;
        area.h = h;
        
        // Convert the image into an OpenGL texture.
        mGlyphs[g] = mGraphics->createImage(image, UIImage::FILTER_LINEAR | UIImage::WRAP_CLAMP, &area);
    }

    /* We don't need the original image anymore */
    SDL_FreeSurface(image);

    mLoaded = TRUE;
    return mLoaded;
}


FLOAT UIFontOpenGLSDL::getStringWidth(const char *string, FLOAT scale)
{
    if (string == NULL)
        return 0;

    FLOAT stringWidth = 0;
    UINT g, stringLen = strlen(string);

    for (g = 0; g < stringLen; ++g)
        stringWidth += scale * (mGlyphs[mGlyphMap[(UINT8)string[g]]]->getWidth() + mCharacterSpacing);

    return stringWidth;
}


void UIFontOpenGLSDL::drawString(FLOAT x, FLOAT y, UINT32 flags, const char *string,
                                 FLOAT red, FLOAT green, FLOAT blue, FLOAT alpha, FLOAT scale)
{
    const FLOAT color[4] = { red, green, blue, alpha };
    drawString(x, y, flags, string, color, scale);
}


void UIFontOpenGLSDL::drawString(FLOAT x, FLOAT y, UINT32 flags,
                                 const char *string, const FLOAT *color, FLOAT scale)
{
    if (string == NULL)
        return;

    FLOAT stringWidth = 0, stringHeight = 0;
    UINT g, stringLen = strlen(string);

    if ((flags & ALIGN_HORIZ_CENTER) > 0 ||
        (flags & ALIGN_RIGHT) > 0)
    {
        // calculate row width and adjust x
        for (g = 0; g < stringLen; ++g)
            stringWidth += scale * (mGlyphs[mGlyphMap[(UINT8)string[g]]]->getWidth() + mCharacterSpacing);
        if ((flags & ALIGN_HORIZ_CENTER) > 0)
            x -= stringWidth / 2;
        else if ((flags & ALIGN_RIGHT) > 0)
            x -= stringWidth;
    }
    if ((flags & ALIGN_VERT_CENTER) > 0 ||
        (flags & ALIGN_BOTTOM) > 0)
    {
        // calculate row height and adjust y
        stringHeight = scale * mFontHeight;
        if ((flags & ALIGN_VERT_CENTER) > 0)
            y -= stringHeight / 2;
        else if ((flags & ALIGN_BOTTOM) > 0)
            y -= stringHeight;
    }
    
    for (g = 0; g < stringLen; ++g)
    {
        const UINT8 ch = (UINT8)string[g];
        const UINT glyphIndex = mGlyphMap[ch];
        UIImageOpenGL *glyph = (UIImageOpenGL *)mGlyphs[glyphIndex];
        glyph->setScale(scale);
        glyph->draw(mDrawMode, UIImage::TRANSFORM | UIImage::COLOR | UIImage::SCALE, x, y, color);
        x += scale * (glyph->getWidth() + mCharacterSpacing);
    }
}
